/**
 * adc_test.c
 * 
 * 使用Linux标准文件操作接口读取ADC值并实现按键动作检测
 */

#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>
#include <errno.h>
#include <time.h>

// 定义ADC设备路径（根据实际硬件平台修改）
#define ADC_DEVICE_PATH "/sys/bus/iio/devices/iio:device0/in_voltage0_raw"

// 定义按键检测参数
#define KEY_DEBOUNCE_TIME_MS 50    // 按键消抖时间（毫秒）
#define KEY_THRESHOLD_LOW 1000     // 按键按下的ADC阈值（低电平）
#define KEY_THRESHOLD_HIGH 3000    // 按键释放的ADC阈值（高电平）

// 按键状态枚举
typedef enum {
    KEY_STATE_RELEASED,
    KEY_STATE_PRESSED,
    KEY_STATE_DEBOUNCING
} key_state_t;

/**
 * 读取ADC值
 * \param adc_value 用于存储读取到的ADC值的指针
 * 
return 0表示成功，其他值表示失败
 */
int read_adc_value(int *adc_value)
{
    int fd = -1;
    char buf[16] = {0};
    int ret = -1;

    // 打开ADC设备文件
    fd = open(ADC_DEVICE_PATH, O_RDONLY);
    if (fd < 0) {
        fprintf(stderr, "Failed to open ADC device: %s\n", strerror(errno));
        return -1;
    }

    // 读取ADC值
    ret = read(fd, buf, sizeof(buf) - 1);
    if (ret < 0) {
        fprintf(stderr, "Failed to read ADC value: %s\n", strerror(errno));
        close(fd);
        return -1;
    }

    // 将读取到的字符串转换为整数
    *adc_value = atoi(buf);

    // 关闭文件
    close(fd);
    return 0;
}

/**
 * 延时函数（毫秒）
 * \param ms 延时时间（毫秒）
 */
void delay_ms(int ms)
{
    // 直接使用unsigned int类型，避免使用可能未定义的useconds_t
    (void)usleep((unsigned int)(ms * 1000));
}

/**
 * 主函数
 */
int main(void)
{
    int adc_value = 0;
    int prev_adc_value = 0;
    key_state_t key_state = KEY_STATE_RELEASED;
    int debounce_timer = 0;
    int key_press_count = 0;
    int key_release_count = 0;

    printf("ADC test program started\n");
    printf("Press Ctrl+C to exit\n");
    printf("\nADC Value\tKey State\n");
    printf("------------------------\n");

    // 主循环
    while (1) {
        // 读取ADC值
        if (read_adc_value(&adc_value) < 0) {
            printf("Failed to read ADC, retrying...\n");
            delay_ms(100);
            continue;
        }

        // 按键状态检测
        switch (key_state) {
            case KEY_STATE_RELEASED:
                // 检测按键按下
                if (adc_value < KEY_THRESHOLD_LOW) {
                    key_state = KEY_STATE_DEBOUNCING;
                    debounce_timer = KEY_DEBOUNCE_TIME_MS;
                }
                break;

            case KEY_STATE_PRESSED:
                // 检测按键释放
                if (adc_value > KEY_THRESHOLD_HIGH) {
                    key_state = KEY_STATE_DEBOUNCING;
                    debounce_timer = KEY_DEBOUNCE_TIME_MS;
                }
                break;

            case KEY_STATE_DEBOUNCING:
                // 消抖延时
                debounce_timer -= 10;  // 假设每次循环大约10ms
                if (debounce_timer <= 0) {
                    if (adc_value < KEY_THRESHOLD_LOW) {
                        key_state = KEY_STATE_PRESSED;
                        key_press_count++;
                        printf("\rKey pressed!\tCount: %d\n", key_press_count);
                    } else {
                        key_state = KEY_STATE_RELEASED;
                        key_release_count++;
                    }
                }
                break;

            default:
                key_state = KEY_STATE_RELEASED;
                break;
        }

        // 每秒更新一次ADC值显示
        if (prev_adc_value != adc_value) {
            printf("\r%d\t\t%s    ", 
                   adc_value, 
                   key_state == KEY_STATE_PRESSED ? "Pressed" : "Released");
            fflush(stdout);
            prev_adc_value = adc_value;
        }

        // 延时10ms，降低CPU占用
        delay_ms(10);
    }

    return 0;
}